package rd0910;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.List;

import fr.irstv.dataModel.CircleKDistance;
import fr.irstv.dataModel.DataPoint;
import fr.irstv.dataModel.MkDataPoint;
import fr.irstv.dataModel.Segment;
import fr.irstv.kmeans.DataGroup;
import fr.irstv.kmeans.DataMk;
import fr.irstv.kmeans.RanSac;
import fr.irstv.view.ImageFilter;

import ij.IJ;
import ij.ImagePlus;
import ij.process.ImageProcessor;


public class VanishingPoints {

	/**
	 * path to images and xml files
	 */
	public static String imagePath ;
	public static String xmlFilePath;

	/**
	 * desired images size for output
	 */
	public static final int resultWidth = 2000;
	
	private static Color[] colors = { Color.blue,
		Color.green, Color.red, Color.yellow,Color.cyan, Color.magenta,
		Color.orange, Color.pink };
	
	public VanishingPoints(File file){
		xmlFilePath = ImageFilter.getFileNameWithoutExtension(file.getPath()) + ".xml";
		imagePath = file.getPath();
	}
	
	public DataGroup[] run(ImageProcessor orig) {
		
		CircleKDistance fd = new CircleKDistance();
		fd.setScilabCheck(true);
		
		DataMk dataSet=null;
		try {
			dataSet = new DataMk(xmlFilePath);
			System.out.println("--debug-- "+dataSet.getCorpus().size()+" elements to classify");
			long a = -System.currentTimeMillis();
			// here we launch the real job
			RanSac r = new RanSac(6,dataSet,fd);
			// param init
			r.setMaxSample(5);
			r.setSigma(40d);
			r.setStopThreshold(0.1d);
			r.go();
			a += System.currentTimeMillis();
			IJ.showStatus("--Vanishing Points-- Computation terminated in "+((float)a)/1000f+"s");		
			// let's load the image and display some results
			ImagePlus originalImage = new ImagePlus(imagePath);
			ImageProcessor ip = originalImage.getProcessor();
			convertToLowGrey(ip);
			drawSortedSegments(r,ip);
			//originalImage.show();
			//originalImage.updateAndDraw();
			
			// let's try to draw the same image with the vanishing points
			displayVP(r.getGroups(),ip,originalImage);
			
			return r.getGroups();
			
		} catch (IOException e) {
			IJ.error("Vanishing point detection plugin","I/O error while accessing file "+xmlFilePath);
			return null;
		}
		
	}
	
	private void drawSegments(List<DataPoint> dataSet,ImageProcessor ip,Color c) {
		ip.setColor(c);
		for (DataPoint dp : dataSet) {
			if (dp instanceof MkDataPoint) {
				Segment s = ((MkDataPoint) dp).getSeg();
				ip.drawLine((int)s.getBeginPoint().get(0),(int)s.getBeginPoint().get(1),
						(int)s.getEndPoint().get(0),(int)s.getEndPoint().get(1));
			}
			draw((int)dp.get(0), (int)dp.get(1),ip);
		}
	}

	public void drawSortedSegments(RanSac r,ImageProcessor ip) {
		int n = r.getGroups().length;
		for (int i=0 ; i<Math.min(n,colors.length) ; i++) {
			drawSegments(r.getGroups()[i].getComponents(),ip,colors[i]);
		}
	}
	public int setup(String arg0, ImagePlus imp) {
	       if (arg0.equals("about")) {
	            showAbout();
	            //return DONE;
	            return 1;
	        }
	       else {
	    	   if (arg0.length() == 0) {
	    		   IJ.showMessage("An image name (without suffix) is required as argument!");
	    	   }
	    	   else {
	    		   imagePath = arg0;
	    	   }
	       }
		//return NO_IMAGE_REQUIRED;
	       return 0;
	}

	private void showAbout() {
		// TODO Auto-generated method stub
        String cn = getClass().getName();
        IJ.showMessage("About "+cn+" ...",
            "IRSTV testing of ImageJ."
        );
		
	}

	private void convertToLowGrey(ImageProcessor ip) {
		int w = ip.getWidth();
		int h = ip.getHeight();
		int[] pixels = (int[]) ip.convertToRGB().getPixels();
		for (int i=0 ; i<h ; i++) {
			for (int j=0 ; j<w ; j++) {
				int offset = i*w+j;
				int c = pixels[offset];
				int r = (c & 0xff0000) >> 16;
				int g = (c & 0x00ff00) >> 8;
				int b = (c & 0x0000ff) ;
				// do the job
				int m = (r+g+b)/6; 
				r = g = b = m;
				// modify the pixel
				pixels[offset] = ((r & 0xff) << 16) + ((g & 0xff)<<8) + (b & 0xff);
			}
		}
	}
	void draw(int u,int v,ImageProcessor ip){
		//draw this corner as a cross
		int size = 4;
		ip.drawLine(u-size,v,u+size,v);
		ip.drawLine(u,v-size,u,v+size);
	}

	private void displayVP(DataGroup[] dg,ImageProcessor ip,ImagePlus orig) {
		int xmin = 0;
		int xmax = ip.getWidth();
		int ymin = 0;
		int ymax = ip.getHeight();
		for (int i=0 ; i<dg.length ; i++) {
			if (dg[i].getComponents().size() >= 3) {
				DataPoint dp = dg[i].computeCentroid();
				//System.out.println("Centroid computed at position x=" + dp.get(0) + " and y=" + dp.get(1));
				if (dp.get(0) < xmin) {
					xmin = (int) dp.get(0);
				}
				if (dp.get(0) > xmax) {
					xmax = (int) dp.get(0);
				}
				if (dp.get(1) < ymin) {
					ymin = (int) dp.get(1);
				}
				if (dp.get(1) > ymax) {
					ymax = (int) dp.get(1);
				}				
			}
		}
		int xtrans = (xmin<0 ? -xmin : 0);
		int ytrans = (ymin<0 ? -ymin : 0);
		float scale = (float) resultWidth / (float) (xmax-xmin);
		
		ImageProcessor vpImage = ip.createProcessor((int) (scale*(xmax-xmin)),(int) (scale*(ymax-ymin)));
		ImageProcessor tmp = ip.createProcessor(ip.getWidth(),ip.getHeight());
		tmp.insert(ip,0,0);
		vpImage.insert(tmp.resize((int)(ip.getWidth()*scale),(int)(ip.getHeight()*scale)), 
				(int)(xtrans*scale),(int)(scale*ytrans));
		for (int i=0 ; i<dg.length ; i++) {
			if (dg[i].getComponents().size() >= 3) {
				vpImage.setColor(colors[i]);
				draw((int)((dg[i].getCentroid().get(0)+xtrans)*scale), (int)((dg[i].getCentroid().get(1)+ytrans)*scale), vpImage);
			}
		}
		ImagePlus im2 = new ImagePlus("Vanishing points",vpImage);
		im2.show();
		im2.updateAndDraw();
	}
}
